package com.handmark.pulltorefresh.library.internal;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.handmark.pulltorefresh.library.R;
import com.handmark.pulltorefresh.library.utils.DimensionPixelUtil;
import com.nineoldandroids.animation.ValueAnimator;

/**
 * TODO: document your custom view class.
 */
public class LoadingView extends View {
    private String mLoadingText;
    private int mLoadingColor = Color.RED;
    private int mLoadingCircleNum = 8;
    private int mLoadingCircleSize;
    private int mLoadingDuration = 1000;

    private TextPaint mPaint;

    private float mAnimValue;
    private float mLastAnimValue;

    private List<int[]> mPoints = new ArrayList<int[]>();

    private final static float MAX_ANIM_VALUE = 1.0f;
    private final static float MIN_ANIM_VALUE = 0.2f;

    private double mCriticalValue = 0.05f;

    private ValueAnimator va;

    public LoadingView(Context context) {
        super(context);
        init(null, 0);
    }

    public LoadingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public LoadingView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs, defStyle);
    }

    private void init(AttributeSet attrs, int defStyle) {
        // Load attributes
        final TypedArray a = getContext().obtainStyledAttributes(
                attrs, R.styleable.PagingLoadingView, defStyle, 0);

        mLoadingText = a.getString(R.styleable.PagingLoadingView_loadingText);
        mLoadingColor = a.getColor(R.styleable.PagingLoadingView_loadingColor, Color.BLUE);

        mLoadingCircleNum = a.getInteger(R.styleable.PagingLoadingView_loadingCircleNum, 8);

        int size = a.getInteger(R.styleable.PagingLoadingView_loadingCircleSize, 10);
        mLoadingCircleSize = (int)DimensionPixelUtil.dip2px(getContext(), size);

        for (int i = 0; i < mLoadingCircleNum; i++) {
            int[] point = new int[]{-1, -1};
            mPoints.add(point);
        }

        mLoadingDuration = a.getInteger(R.styleable.PagingLoadingView_loadingDuration, 1000);

        a.recycle();

        mPaint = new TextPaint();
        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        mPaint.setTextAlign(Paint.Align.LEFT);
        mPaint.setColor(mLoadingColor);

        mCriticalValue = Math.min((MAX_ANIM_VALUE - MIN_ANIM_VALUE) / mLoadingCircleNum - 0.01f, 0.05f);
//        startLoading();
    }

    private void startLoading() {
        va = ValueAnimator.ofFloat(MAX_ANIM_VALUE, MIN_ANIM_VALUE);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
				mAnimValue = (Float) animation.getAnimatedValue();
                if (Math.abs(mAnimValue - mLastAnimValue) > mCriticalValue) {
                    invalidate();
                    mLastAnimValue = mAnimValue;
                }
            }
        });
        va.setRepeatCount(-1);
        va.setDuration(mLoadingDuration);
        va.setInterpolator(new LinearInterpolator());
        va.start();
    }

    private void stopLoading() {
        if (va != null) {
            va.removeAllUpdateListeners();
            va = null;
        }
    }

    @Override
    protected void onDraw(final Canvas canvas) {
        super.onDraw(canvas);
        drawLoading(canvas);
    }

    private void drawLoading(Canvas canvas) {

        for (int i = 0; i < mLoadingCircleNum; i++) {
            int[] point = mPoints.get(i);
            if (point[0] == -1 || point[1] == -1) {
                point[0] = (int) (mCenterX + mRadius * Math.cos(2 * Math.PI / mLoadingCircleNum * i));
                point[1] = (int) (mCenterY - mRadius * Math.sin(2 * Math.PI / mLoadingCircleNum * i));
            }
            canvas.drawCircle(point[0], point[1],
                    mLoadingCircleSize / 2 * (float)getRadio(i), mPaint);
        }
    }

    private int mRadius;
    private int mCenterX, mCenterY;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int paddingLeft = getPaddingLeft();
        int paddingTop = getPaddingTop();
        int paddingRight = getPaddingRight();
        int paddingBottom = getPaddingBottom();

        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        width = height = Math.max(width, height);

        setMeasuredDimension(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));

        int contentWidth = width - paddingLeft - paddingRight;
        int contentHeight = height - paddingTop - paddingBottom;

        mCenterX = contentWidth / 2;
        mCenterY = contentHeight / 2;
        mRadius = (contentWidth - mLoadingCircleSize) / 2 - 4;
    }

    private double getRadio(int i) {
        double value = mAnimValue;
        double di = (MAX_ANIM_VALUE - MIN_ANIM_VALUE) / mLoadingCircleNum;
        value -= di * i;
        if (value - MIN_ANIM_VALUE < 0.000001f) {
            value += (MAX_ANIM_VALUE - MIN_ANIM_VALUE);
        }
        if (value - MAX_ANIM_VALUE > 0.000001f) {
            value -= (MAX_ANIM_VALUE - MIN_ANIM_VALUE);
        }

        if (value - 0.5f < 0.000001f) {
            value = 0.5f;
        }
        return value;
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        startLoading();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        stopLoading();
    }
}
